load("@npm//@angular/build-tooling/bazel:expand_template.bzl", "expand_template")
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary", "nodejs_test")
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@npm//@bazel/esbuild:index.bzl", "esbuild")
load("@npm//@bazel/terser:index.bzl", "terser_minified")
load("//tools:defaults.bzl", "ng_module")

"""
  Performs size measurements for the specified file. The file will be built as part
  of a `ng_module` and then will be optimized with esbuild, babel and terser.

  The resulting size will be validated against a golden file to ensure that we don't
  regress in payload size, or that we can improvements to payload size.
"""

def size_test(name, file, deps):
    # Generates an unique id for the given size test. e.g. if the macro is called
    # within the `integration/size-test/material` package with `name = list`, then
    # the unique id will be set to `material/list`.
    test_id = "%s/%s" % (native.package_name()[len("integration/size-test/"):], name)
    index_file = "%s_autogenerated_module_index.ts" % name

    expand_template(
        name = "%s_index" % name,
        output_name = index_file,
        template = "//integration/size-test:index-tmpl.ts",
        substitutions = {
            "$TEST_FILE": paths.split_extension(file)[0],
        },
    )

    ng_module(
        name = "%s_lib" % name,
        srcs = ["%s.ts" % name, index_file],
        testonly = True,
        deps = [
            "@npm//@angular/core",
            "@npm//@angular/platform-browser",
        ] + deps,
    )

    esbuild(
        name = "%s_bundle" % name,
        config = "//integration/size-test:esbuild_config",
        testonly = True,
        minify = True,
        entry_point = index_file,
        deps = [
            ":%s_lib" % name,
        ],
        target = "es2020",
        platform = "browser",
        # Link the workspace root so that files can be loaded from the workspace.
        link_workspace_root = True,
        sourcemap = "external",
        sources_content = True,
    )

    terser_minified(
        testonly = True,
        name = "%s_bundle_min" % name,
        src = "%s_bundle" % name,
        config_file = "//integration/size-test:terser-config.json",
        sourcemap = False,
    )

    nodejs_test(
        name = name,
        data = [
            "//goldens:size-test.yaml",
            "//integration/size-test:check-size",
            ":%s_bundle_min" % name,
        ],
        entry_point = "//integration/size-test:check-size.ts",
        args = [test_id, "$(rootpath :%s_bundle_min)" % name],
    )

    nodejs_binary(
        name = "%s.approve" % name,
        testonly = True,
        templated_args = ["--bazel_patch_module_resolver"],
        data = [
            "//goldens:size-test.yaml",
            "//integration/size-test:check-size",
            ":%s_bundle_min" % name,
        ],
        entry_point = "//integration/size-test:check-size.ts",
        args = [test_id, "$(rootpath :%s_bundle_min)" % name, "true"],
    )
